Flutter / Examples / * Project 19 : Ecommerce App 2
UI Ecommerce APP
-
Screen 1
UI
File
main.dart
import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'screens/home/home_screen.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, theme: ThemeData( textTheme:GoogleFonts.afacadTextTheme() ), home: const HomeScreen(), ); } } screens/home/home_screen.dart
import 'package:b/models/data_model.dart'; import 'package:b/screens/home/category_selection.dart'; import 'package:b/screens/home/producr_items.dart'; import 'package:flutter/material.dart'; class HomeScreen extends StatelessWidget { const HomeScreen({super.key}); @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, body: SafeArea( child: Column( children: [ myAppBar(), // for search bar mySearchBar(), // for a list of category, const CategorySelection(), // for disply all product itmes ProductItems(), ], )), ); } Padding mySearchBar() { return Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: Container( width: double.infinity, height: 65, decoration: BoxDecoration( color: Colors.black.withOpacity(0.05), borderRadius: BorderRadius.circular(20), ), child: const TextField( decoration: InputDecoration( border: OutlineInputBorder(borderSide: BorderSide.none), contentPadding: EdgeInsets.symmetric(vertical: 20, horizontal: 30), fillColor: Colors.white, hintText: "Search...", hintStyle: TextStyle( fontWeight: FontWeight.bold, fontSize: 20, color: Colors.black26, ), prefixIcon: Icon( Icons.search, size: 30, color: Colors.black26, )), ), ), ); } Padding myAppBar() { return Padding( padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 25), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Icon( Icons.arrow_back_ios, size: 25, ), const Text( "Explore", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20), ), Image.asset( "images/menu.png", height: 25, ) ], ), ); } } screens/home/category_selection.dart
import 'package:b/models/data_model.dart'; import 'package:flutter/material.dart'; class CategorySelection extends StatefulWidget { const CategorySelection({super.key}); @override State createState() => _CategorySelectionState(); } class _CategorySelectionState extends State { int selectedIndex = 1; @override Widget build(BuildContext context) { Size size = MediaQuery.of(context).size; return Padding( padding: const EdgeInsets.only(top: 30), child: SizedBox( height: size.height * 0.05, child: ListView.builder( scrollDirection: Axis.horizontal, itemCount: categoryList.length, physics: const BouncingScrollPhysics(), itemBuilder: (context, index) { return GestureDetector( onTap: () { setState(() { selectedIndex = index; }); }, child: Padding( padding: const EdgeInsets.only(left: 30), child: Column( children: [ Text( categoryList[index], style: TextStyle( color: selectedIndex == index ? Colors.black : Colors.black26, fontSize: 18, fontWeight: selectedIndex == index ? FontWeight.w500 : FontWeight.normal), ), Container( height: 3, width: 26, decoration: BoxDecoration( color: selectedIndex == index ? Colors.orange : Colors.transparent, borderRadius: BorderRadius.circular(30), ), ) ], ), ), ); }), ), ); } } screens/home/product_items.dart
1. GridView.builder
import 'package:b/models/data_model.dart'; import 'package:b/screens/Detail/detail_screen.dart'; import 'package:flutter/material.dart'; class ProductItems extends StatelessWidget { const ProductItems({super.key}); @override Widget build(BuildContext context) { return Expanded( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 20), child: GridView.builder( shrinkWrap: true, physics: const BouncingScrollPhysics(), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, childAspectRatio: 0.65, ), itemCount: productItems.length, itemBuilder: (context, index) { Size size = MediaQuery.of(context).size; final product = productItems[index]; return Transform.translate( offset: Offset(0, index.isOdd ? 28 : 0), child: GestureDetector( onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => DetailScreen(products: product))); }, child: Padding( padding: const EdgeInsets.only(right: 10, left: 10, top: 10), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ ClipRRect( borderRadius: BorderRadius.circular(20), child: Hero( tag: product.imageUrl, child: Image( height: size.height * 0.25, width: size.width * 0.45, image: AssetImage( product.imageUrl, ), fit: BoxFit.cover, ), ), ), const SizedBox( height: 5, ), Text( product.name, style: const TextStyle( color: Colors.black, fontWeight: FontWeight.bold, fontSize: 18, ), ), Text( product.manufacturer, style: const TextStyle( color: Colors.black45, fontWeight: FontWeight.w300, fontSize: 14, ), ) ], ), ), ), ); }), ), ); } } screens/Detail/detail_screen.dart
import 'package:b/models/data_model.dart'; import 'package:b/screens/Detail/product_detail_image.dart'; import 'package:b/screens/Detail/product_item_detail.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; class DetailScreen extends StatelessWidget { const DetailScreen({super.key, required this.products}); final ProductModel products; @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, body: SingleChildScrollView( child: Stack( clipBehavior: Clip.none, children: [ // for product detail images. ProductDetailImages(imageUrl: products.imageUrl), // for product item more detail ProductItemsDetail(product: products), Padding( padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 60), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ GestureDetector( onTap: () { Navigator.pop(context); }, child: const Icon( Icons.arrow_back_ios, size: 30, color: Colors.white, ), ), Image.asset( "images/menu.png", color: Colors.white, height: 25, ) ], ), ) ], ), ), ); } } screens/Detail/curve_image_slide.dart
import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; class CurveImageSide extends CustomClipper { @override Path getClip(Size size) { Path path = Path(); path.lineTo(0, size.height); Offset curve1 = Offset(0, size.height * 0.8); Offset curve2 = Offset(size.width * 0.25, size.height * 0.8); path.quadraticBezierTo( curve1.dx, curve1.dy, curve2.dx, curve2.dy, ); path.lineTo(size.width * 0.75, size.height * 0.8); Offset curve3 = Offset(size.width, size.height * 0.8); Offset curve4 = Offset(size.width, size.height * 0.65); path.quadraticBezierTo( curve3.dx, curve3.dy, curve4.dx, curve4.dy, ); path.lineTo(size.width, 0); path.close(); return path; } @override bool shouldReclip(covariant CustomClipper oldClipper) { return false; } } screens/Detail/product_detail_image.dart
import 'package:flutter/material.dart'; import 'curve_image_side.dart'; class ProductDetailImages extends StatelessWidget { const ProductDetailImages({super.key, required this.imageUrl}); final String imageUrl; @override Widget build(BuildContext context) { Size size = MediaQuery.of(context).size; return ClipPath( clipper: CurveImageSide(), child: Align( alignment: Alignment.topCenter, child: Center( child: Hero( tag: imageUrl, child: Image( fit: BoxFit.cover, height: size.height *0.6, width: size.width, image: AssetImage( imageUrl, )), ), ), ), ); } } screens/Detail/product_item_detail.dart
import 'package:b/models/data_model.dart'; import 'package:b/screens/Detail/star_rating.dart'; import 'package:flutter/material.dart'; class ProductItemsDetail extends StatelessWidget { const ProductItemsDetail({super.key, required this.product}); final ProductModel product; @override Widget build(BuildContext context) { Size size = MediaQuery.of(context).size; return Positioned( top: size.height * 0.52, child: SizedBox( width: size.width, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 35), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( product.name, style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 52, color: Colors.black), ), Text( product.manufacturer, style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 18, color: Colors.black38), ) ], ), Text( '\$${product.price}', style: const TextStyle( fontWeight: FontWeight.bold, letterSpacing: -1, fontSize: 20, color: Colors.deepOrange), ), ], ), const SizedBox( height: 5, ), Row( children: [ Text( '${product.rating}.0', style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 17, color: Colors.deepOrange), ), const SizedBox( width: 5, ), StarRating(rating: product.rating), ], ), const SizedBox( height: 30, ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( "fabric color", style: TextStyle(fontSize: 20, color: Colors.black38), ), Text( product.fabricColor, style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 20, color: Colors.black), ), ], ), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( "style", style: TextStyle(fontSize: 20, color: Colors.black38), ), Text( product.style, style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 20, color: Colors.black), ), ], ), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( "made in", style: TextStyle(fontSize: 20, color: Colors.black38), ), Text( product.madeIn, style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 20, color: Colors.black), ), ], ) ], ), const SizedBox( height: 30, ), Text( product.description, style: const TextStyle( fontWeight: FontWeight.w600, height: 1.2, fontSize: 18, color: Colors.black45), ), const SizedBox( height: 30, ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Container( width: size.width * 0.64, height: 75, decoration: BoxDecoration( color: Colors.black, borderRadius: BorderRadius.circular(25), ), child: const Center( child: Text( "Pay", style: TextStyle( fontWeight: FontWeight.w900, fontSize: 22, color: Colors.white, ), ), ), ), Container( width: size.width * 0.18, height: 75, decoration: BoxDecoration( color: Colors.black12, borderRadius: BorderRadius.circular(27), ), child: const Center( child: Icon( Icons.favorite_border_rounded, size: 30, color: Colors.black38, )), ), ], ) ], ), ), ), ); } } screens/Detail/star_rating.dart
import 'package:flutter/material.dart'; class StarRating extends StatefulWidget { const StarRating({super.key, required this.rating}); final int rating; @override State createState() => _StarRatingState(); } class _StarRatingState extends State { Widget star(bool fill) { return Icon( Icons.star, size: 20, color: fill ? Colors.deepOrange : Colors.black45, ); } // push the video and see it you can understand easily @override Widget build(BuildContext context) { return Row( mainAxisAlignment: MainAxisAlignment.center, children: List.generate(5, (index) { if (index < (widget.rating).round()) { return star(true); } else { return star(false); } }), ); } } models/data_model.dart
class ProductModel { String name; String imageUrl; int price; String manufacturer; String description; String fabricColor; int rating; String style; String madeIn; ProductModel({ required this.name, required this.imageUrl, required this.price, required this.manufacturer, required this.description, required this.fabricColor, required this.rating, required this.style, required this.madeIn, }); } List productItems = [ ProductModel( name: 'Hanging Chair', manufacturer: 'by Carl MH Barenbrug', imageUrl: 'images/hanging chair.png', price: 2222, fabricColor: 'White', description: 'Sound absorption is a key concept in room acoustics, which may not often be considered in furniture design', madeIn: 'Japan', rating: 4, style: 'Modern', ), ProductModel( name: 'Tune Sofa', manufacturer: 'by Carl MH Barenbrug', imageUrl: 'images/Tune Sofa.png', price: 1695, fabricColor: 'Silver', description: 'Sound absorption is a key concept in room acoustics, which may not often be considered in furniture design', madeIn: 'Russia', rating: 5, style: 'Modern', ), ProductModel( name: 'EMKO Naive', manufacturer: 'by Carl MH Barenbrug', imageUrl: 'images/EMKO Naive.png', price: 1111, fabricColor: 'White', description: 'Sound absorption is a key concept in room acoustics, which may not often be considered in furniture design', madeIn: 'Russia', rating: 3, style: 'Modern', ), ProductModel( name: 'Reform', manufacturer: 'by Carl MH Barenbrug', imageUrl: 'images/Reform.png', price: 120, fabricColor: 'White', description: 'Sound absorption is a key concept in room acoustics, which may not often be considered in furniture design', madeIn: 'Russia', rating: 4, style: 'Modern', ), ProductModel( name: 'Ella Armchair', manufacturer: 'by Carl MH Barenbrug', imageUrl: 'images/Ella Armchair.png', price: 1695, fabricColor: 'White', description: 'Sound absorption is a key concept in room acoustics, which may not often be considered in furniture design', madeIn: 'Russia', rating: 4, style: 'Modern', ), ProductModel( name: 'Wooden Chair', manufacturer: 'by Carl MH Barenbrug', imageUrl: 'images/Wooden Chair.png', price: 1200, fabricColor: 'Wooden', description: 'Sound absorption is a key concept in room acoustics, which may not often be considered in furniture design', madeIn: 'Russia', rating: 4, style: 'Classic', ), ]; List categoryList = [ 'Interiors', 'Furniture', 'Moods', 'Creators', 'Home Appliances' ];